package com.yanyu.space.common.cloud.feign;

import com.alibaba.fastjson.JSONObject;
import feign.Request;
import feign.Response;
import feign.Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;

import static feign.Util.UTF_8;
import static feign.Util.decodeOrDefault;

/**
 * @author gz
 */
@Slf4j
public class FeignCustomLogger extends feign.Logger {

    private Logger logger;

    public FeignCustomLogger() {
        this(feign.Logger.class);
    }

    public FeignCustomLogger(Class<?> clazz) {
        this(LoggerFactory.getLogger(clazz));
    }

    FeignCustomLogger(Logger logger) {
        this.logger = logger;
    }

    @Override
    protected void logRequest(String configKey, Level logLevel, Request request) {
        Map<String, Collection<String>> params = request.requestTemplate().queries();
        String query = MapUtils.isNotEmpty(params) ? JSONObject.toJSONString(params) : null;
        if (request.body() != null) {
            if (logLevel.ordinal() >= Level.FULL.ordinal()) {
                String bodyText =
                        request.charset() != null
                                ? new String(request.body(), request.charset())
                                : null;
                bodyText = bodyText != null ? bodyText : "Binary data";
                log(configKey, "请求参数 ---> method: %s url: %s  body: %s", request.httpMethod().name(), request.url(), query, bodyText);
            }
        } else {
            log(configKey, "请求参数 ---> method: %s url: %s  body: %s", request.httpMethod().name(), request.url(), query, null);
        }
    }

    @Override
    protected Response logAndRebufferResponse(String configKey,
                                              Level logLevel,
                                              Response response,
                                              long elapsedTime) throws IOException {
        int status = response.status();
        if (response.body() != null && !(status == 204 || status == 205)) {
            byte[] bodyData = Util.toByteArray(response.body().asInputStream());
            int bodyLength = bodyData.length;
            if (bodyLength > 0) {
                log(configKey, "响应结果 ---> status： %s (%sms) body：%s", status, elapsedTime, decodeOrDefault(bodyData, UTF_8, "Binary data"));
            }
            return response.toBuilder().body(bodyData).build();
        } else {
            log(configKey, "响应结果 ---> status： %s (%sms) body：%s", status, elapsedTime, null);
        }
        return response;
    }

    @Override
    protected IOException logIOException(String configKey, Level logLevel, IOException ioe, long elapsedTime) {
        log(configKey, "响应异常 ---> %s: %s (%sms)", ioe.getClass().getSimpleName(), ioe.getMessage(),
                elapsedTime);
        return ioe;
    }

    @Override
    protected void log(String configKey, String format, Object... args) {
        log.info(String.format(methodTag(configKey) + format, args));
    }
}
